package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.*;
import com.sc.nft.dto.UserEcologyHatchRecordsDao;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.ExamineAndApproveDTO;
import com.sc.nft.entity.dto.ServiceCenterAuditAddDTO;
import com.sc.nft.entity.dto.ServiceCenterAuditDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.ApplicationRequirementEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.factory.ApplicationRequirementFactory;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.ServiceCenterAuditService;
import com.sc.nft.service.UserMarketValueService;
import com.sc.nft.service.UserPerformanceService;
import com.sc.nft.sup.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (ServiceCenterAudit)表服务实现类
 *
 * @author wwc
 * @since 2023-07-18 14:40:11
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ServiceCenterAuditServiceImpl implements ServiceCenterAuditService {

    private final ServiceCenterAuditDao serviceCenterAuditDao;

    private final UserCityServerCentreDao userCityServerCentreDao;

    private final ApplicationRequirementDao applicationRequirementDao;

    private final UserWorkRoomDao userWorkRoomDao;

    private final UserPerformanceService userPerformanceService;

    private final ApplicationRequirementFactory applicationRequirementFactory;

    private final UserInfoDao userInfoDao;

    private final IdcardInfoDao idcardInfoDao;

    private final UserMarketValueService userMarketValueService;

    private final UserMarketValueDao userMarketValueDao;

    private final UserEcologyHatchRecordsDao userEcologyHatchRecordsDao;


    @Override
    public Page<ServiceCenterAuditVO> compactPage(ServiceCenterAuditDTO serviceCenterAuditDTO) {
        return serviceCenterAuditDao.compactPage(serviceCenterAuditDTO.toMp(), serviceCenterAuditDTO);
    }

    @Override
    public ServiceCenterAuditDetailsVO getById(Long id) {
        ServiceCenterAudit serviceCenterAudit = serviceCenterAuditDao.getById(id);
        return BeanUtil.copyProperties(serviceCenterAudit, ServiceCenterAuditDetailsVO.class);
    }

    @Override
    public void examineAndApprove(ExamineAndApproveDTO examineAndApproveDTO) {
        ServiceCenterAudit result = serviceCenterAuditDao.getByIdAndType(examineAndApproveDTO.getId(), examineAndApproveDTO.getType());
        if (BeanUtil.isEmpty(result)) {
            throw new GlobalRunTimeException("数据不存在");
        }
        if (result.getType().equals(2)) {
            Long userId = result.getUserId();
            UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(userId);
            if (BeanUtil.isNotEmpty(userCityServerCentre)) {
                throw new GlobalRunTimeException("该用户已经是服务中心");
            }
        }
        if (result.getType().equals(1)) {
            Long userId = result.getUserId();
            UserWorkRoom userWorkRoom = userWorkRoomDao.selectByUserId(userId);
            if (BeanUtil.isNotEmpty(userWorkRoom)) {
                throw new GlobalRunTimeException("该用户已经是社区网点");
            }
        }
        ServiceCenterAudit serviceCenterAudit = BeanUtil.copyProperties(examineAndApproveDTO, ServiceCenterAudit.class);
        serviceCenterAudit.setAuditTime(new Date());
        serviceCenterAudit.updateById();
    }

    @Override
    public void add(ServiceCenterAuditAddDTO serviceCenterAuditAddDTO) {
        UserInfo user = UserPool.getUser();
        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(user.getId());
        if (ObjectUtil.isNull(idcardInfo)){
            throw new GlobalRunTimeException(ErrorCode.PLEASE_PERFORM_REAL_NAME_AUTHENTICATION_FIRST);
        }
        String name = idcardInfo.getName();
        if (StrUtil.isBlank(name)){
            throw new GlobalRunTimeException("找不到实名信息");
        }
        if (StrUtil.isBlank(idcardInfo.getCardId())){
            throw new GlobalRunTimeException("找不到身份证信息");
        }
        serviceCenterAuditAddDTO.setUserName(name);
        serviceCenterAuditAddDTO.setIdentityCard(idcardInfo.getCardId());
        if (serviceCenterAuditAddDTO.getId() != null) {
            // 如果不为空，说明是修改
            ServiceCenterAudit serviceCenterAudit = serviceCenterAuditDao.getById(serviceCenterAuditAddDTO.getId());
            if (BeanUtil.isEmpty(serviceCenterAudit)) {
                throw new GlobalRunTimeException("数据不存在");
            }
            if (serviceCenterAudit.getStatus().equals(1)) {
                throw new GlobalRunTimeException("审核已通过");
            }
            ServiceCenterAudit serviceCenterAudit1 = BeanUtil.copyProperties(serviceCenterAuditAddDTO, ServiceCenterAudit.class);
            serviceCenterAudit1.setUserId(user.getId());
            serviceCenterAudit1.setStatus(0);
            serviceCenterAudit1.updateById();
            return;
        }
        ServiceCenterAudit oneByUserId = serviceCenterAuditDao.getOneByUserIdAndType(user.getId(),serviceCenterAuditAddDTO.getType());
        if (BeanUtil.isNotEmpty(oneByUserId)) {
            if (oneByUserId.getStatus().equals(0)) {
                throw new GlobalRunTimeException("您已经提交过申请，请勿重复提交");
            }
            if (oneByUserId.getStatus().equals(1)) {
                throw new GlobalRunTimeException("审核已通过");
            }
        }
        ServiceCenterAudit serviceCenterAudit = BeanUtil.copyProperties(serviceCenterAuditAddDTO, ServiceCenterAudit.class);
        serviceCenterAudit.setUserId(user.getId());
        serviceCenterAudit.setUserStatus(user.getLevelName());
        serviceCenterAudit.setStatus(0);
        serviceCenterAudit.insert();
    }

    @Override
    public ServiceCenterAuditDisplayTypeVO displayType(UserInfo user, Integer type) {
        ServiceCenterAuditDisplayTypeVO serviceCenterAuditDisplayTypeVO = new ServiceCenterAuditDisplayTypeVO();
        // 获取城市服务中心是否存在
        UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(user.getId());

        if (BeanUtil.isNotEmpty(userCityServerCentre)) {
            if (type.equals(2)) {
                serviceCenterAuditDisplayTypeVO.setStatus(4);
            }
            serviceCenterAuditDisplayTypeVO.setType(2);
            return serviceCenterAuditDisplayTypeVO;
        }

        // 获取社区服务中心是否存在
        UserWorkRoom userWorkRoom = userWorkRoomDao.selectByUserId(user.getId());

        if (type.equals(1)) {
            if (BeanUtil.isNotEmpty(userWorkRoom)) {
                if (type.equals(1)) {
                    serviceCenterAuditDisplayTypeVO.setStatus(4);
                }
                serviceCenterAuditDisplayTypeVO.setType(1);
                return serviceCenterAuditDisplayTypeVO;
            }
        }
        ServiceCenterAudit oneByUserId = serviceCenterAuditDao.getByUserIdAndType(user.getId(), type);
        if (BeanUtil.isEmpty(oneByUserId)) {
            serviceCenterAuditDisplayTypeVO.setStatus(0);
            serviceCenterAuditDisplayTypeVO.setType(0);
            return serviceCenterAuditDisplayTypeVO;
        }
        if (oneByUserId.getType().equals(type)) {
            if (oneByUserId.getStatus().equals(0)) {
                serviceCenterAuditDisplayTypeVO.setStatus(1);
            }
            if (oneByUserId.getStatus().equals(1)) {
                serviceCenterAuditDisplayTypeVO.setStatus(2);
            }

            if (oneByUserId.getStatus().equals(2)) {
                serviceCenterAuditDisplayTypeVO.setStatus(3);
                serviceCenterAuditDisplayTypeVO.setRefuse(oneByUserId.getRefuse());
            }
        }
        serviceCenterAuditDisplayTypeVO.setType(0);
        return serviceCenterAuditDisplayTypeVO;
    }

    @Override
    public void withdraw(UserInfo user,Integer type) {
        ServiceCenterAudit oneByUserId = serviceCenterAuditDao.getByUserIdAndType(user.getId(),type);
        if (BeanUtil.isNotEmpty(oneByUserId)) {
            if (oneByUserId.getStatus().equals(1)) {
                throw new GlobalRunTimeException("审核已通过,无法撤回");
            }
            if (oneByUserId.getStatus().equals(2)) {
                throw new GlobalRunTimeException("审核已驳回,无需撤回");
            }
            if (oneByUserId.getStatus().equals(0)) {
                oneByUserId.setStatus(3);
                oneByUserId.updateById();
            }
        }
    }

    @Override
    public ServiceCenterAuditDetailsVO recyclingBin(UserInfo user,Integer type) {
        ServiceCenterAudit oneByUserId = serviceCenterAuditDao.getByUserIdAndType(user.getId(),type);
        if (BeanUtil.isEmpty(oneByUserId)) {
            // 如果没有,需要把用户名  身份证 手机号  给返回去
            IdcardInfo byUserIdAndIsPass = idcardInfoDao.getByUserIdAndIsPass(user.getId());
            if (BeanUtil.isEmpty(byUserIdAndIsPass)) {
                throw new GlobalRunTimeException("用户信息不完善,未进行实名制认证.无法申请");
            }
            ServiceCenterAuditDetailsVO serviceCenterAuditDetailsVO = new ServiceCenterAuditDetailsVO();
            serviceCenterAuditDetailsVO.setIdentityCard(DesensitizedUtil.idCardNum(byUserIdAndIsPass.getCardId(), 1 , 1));
            serviceCenterAuditDetailsVO.setUserTel(user.getUserTel());
            String name = byUserIdAndIsPass.getName();
            serviceCenterAuditDetailsVO.setUserName(StrUtil.isNotBlank(name) ? StrUtil.hide(name,0,name.length()-1) : StrUtil.EMPTY);
            return serviceCenterAuditDetailsVO;
        }
        ServiceCenterAuditDetailsVO result = BeanUtil.copyProperties(oneByUserId, ServiceCenterAuditDetailsVO.class);
        String name = oneByUserId.getUserName();
        result.setUserName(StrUtil.isNotBlank(name) ? StrUtil.hide(name,0,name.length()-1) : StrUtil.EMPTY);
        result.setIdentityCard(DesensitizedUtil.idCardNum(oneByUserId.getIdentityCard(), 1 , 1));
        return result;
    }

    @Override
    public GetWorkRoomOrCityServiceNameVO getWorkRoomOrCityServiceName(UserInfo user, Integer type) {
        GetWorkRoomOrCityServiceNameVO getWorkRoomOrCityServiceNameVO = new GetWorkRoomOrCityServiceNameVO();
        if (type.equals(2)) {
            // 获取社区服务中心是否存在
            UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(user.getId());
            if (BeanUtil.isEmpty(userCityServerCentre)) {
                throw new GlobalRunTimeException("服务中心不存在");
            }
            getWorkRoomOrCityServiceNameVO.setName(StrUtil.format("{}-{}-{}", userCityServerCentre.getProvince(), userCityServerCentre.getCity(), userCityServerCentre.getDistrict()));
            return getWorkRoomOrCityServiceNameVO;
        }

        if (type.equals(1)) {
            // 获取社区服务中心是否存在
            UserWorkRoom userWorkRoom = userWorkRoomDao.selectByUserId(user.getId());
            if (BeanUtil.isEmpty(userWorkRoom)) {
                throw new GlobalRunTimeException("工作室不存在");
            }
            getWorkRoomOrCityServiceNameVO.setName(userWorkRoom.getWorkName());
            return getWorkRoomOrCityServiceNameVO;
        }
        return null;
    }

    @Override
    public PerformanceVO performance(UserInfo userInfo) {
        Boolean urbanServiceCenter=Boolean.TRUE;
        UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(userInfo.getId());
        if (BeanUtil.isEmpty(userCityServerCentre)) {
            urbanServiceCenter=Boolean.FALSE;
        }
        Long userId = userInfo.getId();
        BigDecimal teamPerformanceThisWeek = userPerformanceService.getPerformanceNearDate(userId, 7,urbanServiceCenter);
        BigDecimal teamPerformanceThisMonth = userPerformanceService.getPerformanceNearDate(userId, 30,urbanServiceCenter);
        PerformanceVO performanceVO = new PerformanceVO();
        performanceVO.setTeamPerformanceThisWeek(teamPerformanceThisWeek);
        performanceVO.setTeamPerformanceThisMonth(teamPerformanceThisMonth);
        // 根据结果集的id,获取用户持仓成本
//        BigDecimal theTotalPerformanceOfTheUserTeam = userCollectionDao.getTheTotalPerformanceOfTheUserTeam( userInfo.getId(), null,urbanServiceCenter);
        BigDecimal theTotalPerformanceOfTheUserTeam = userMarketValueService.getEcologyMarketValue(userInfo.getId());
        performanceVO.setTeamCost(theTotalPerformanceOfTheUserTeam);
        Integer byListUserIdCountValid = userInfoDao.getByListUserIdCountValid(userInfo.getId(),urbanServiceCenter);
        performanceVO.setValidatedUser(byListUserIdCountValid);
        Integer teamCityServiceCenter = userWorkRoomDao.getsHowManyCommunityOutletsAreIncludedInTheSpecifiedCollection(userId);
        performanceVO.setTeamCommunityNetwork(teamCityServiceCenter);
        Integer teamCommunityNetwork = userCityServerCentreDao.teamCityServiceCenter(userId);
        performanceVO.setTeamCityServiceCenter(teamCommunityNetwork);
        return performanceVO;
    }

    @Override
    public WebApplicationRequirementVO totalPerformance(Long id) {
        ServiceCenterAudit serviceCenterAudit = serviceCenterAuditDao.getById(id);
        if (BeanUtil.isEmpty(serviceCenterAudit)) {
            throw new GlobalRunTimeException("审核数据不存在");
        }

        // 根据type获取对应的数据
        List<ApplicationRequirement> applicationRequirements = applicationRequirementDao.selectListByType(serviceCenterAudit.getType());
        // applicationRequirements 中的groupId进行分组
        UserInfo user = userInfoDao.getById(serviceCenterAudit.getUserId());
        List<WebApplicationRequirementWhereVO> result = new ArrayList<>();
        Map<Integer, List<ApplicationRequirement>> taskGroupMap = applicationRequirements.stream().collect(Collectors.groupingBy(ApplicationRequirement::getTaskGroup));
        // 将分组后的数据进行遍历,并且将结果集放入到multiLevelList中
        taskGroupMap.forEach((k, v) -> {
            // 在根据groupId进行分组,分组的数据是每个申请条件的组合
            Map<Integer, List<ApplicationRequirement>> groupedByGroupId = v.stream()
                    .collect(Collectors.groupingBy(ApplicationRequirement::getGroupId));
            // 分组后的数据获取对应用户的数据组合好.

            // 这个是and的条件,必须满足
            List<ApplicationRequirementFactoryVO> andList = new ArrayList<>();
            // 这个是多组or的条件容器用来装orList
            List<List<ApplicationRequirementFactoryVO>>multiLevelList = new ArrayList<>();
            WebApplicationRequirementWhereVO webApplicationRequirementWhereVO=new WebApplicationRequirementWhereVO();
            groupedByGroupId.forEach((k1, v1) -> {
                // 这个是装or的条件
                List<ApplicationRequirementFactoryVO> orList = new ArrayList<>();
                v1.forEach(applicationRequirement -> {
                    ApplicationRequirementFactoryVO applicationRequirementFactoryVO = applicationRequirementFactory.getApplicationRequirementFactoryService(applicationRequirement.getType().getCode())
                            .applicationRequirement(user, applicationRequirement, serviceCenterAudit.getType());
                    if ("AND".equals(applicationRequirement.getCompoundMode())) {
                        andList.add(applicationRequirementFactoryVO);
                    } else {
                        orList.add(applicationRequirementFactoryVO);
                    }
                });
                if (CollUtil.isNotEmpty(orList)) {
                    multiLevelList.add(orList);
                }
            });
            // 一个完整的申请条件,写入result中
            webApplicationRequirementWhereVO.setOrList(multiLevelList);
            webApplicationRequirementWhereVO.setAndList(andList);
            webApplicationRequirementWhereVO.setSatisfy(webApplicationRequirementWhereVO.whetherMeetTheRequirement());
            result.add(webApplicationRequirementWhereVO);
        });
        WebApplicationRequirementVO webApplicationRequirementVO = new WebApplicationRequirementVO();
        webApplicationRequirementVO.setResult(result);
        return webApplicationRequirementVO;
    }
    @Override
    public NewPerformanceVO newPerformance(UserInfo user) {
        Long userId=user.getId();
        // 判定当前用户是不是城市服务中心,根据这个参数来决定,是否在获取数据的时候排除他的下级的社区网点和城市服务中心等数据,如果是false的话,就证明他是社区网点 true为城市服务中心
        Boolean exclude=Boolean.TRUE;
        UserCityServerCentre userCityServerCentre = userCityServerCentreDao.selectByUserId(userId);
        if (BeanUtil.isEmpty(userCityServerCentre)) {
            exclude=Boolean.FALSE;
        }
        // 这个type是为了区分他当前是社区网点还是城市服务中心,1是社区网点 2是社区服务中心,没有使用枚举是因为调用ApplicationRequirementService方法接口,参数不是枚举类 早期设计失败导致.
        Integer type=1;
        if (exclude) {
            type=2;
        }
        List<ApplicationRequirement> applicationRequirements = applicationRequirementDao.selectListByServeTypeAndType(type,ApplicationRequirementEnum.IMMEDIATE_ACCOUNT,
                ApplicationRequirementEnum.TEAM_ACCOUNT,ApplicationRequirementEnum.TOTAL_HOLDINGS_OF_TEAM_COLLECTIONS,ApplicationRequirementEnum.TOTAL_TEAM_ECO_MELTING_VALUE);

        NewPerformanceVO newPerformanceVO=new NewPerformanceVO();
        List<ApplicationRequirementFactoryVO>list=new ArrayList<>();
        for (ApplicationRequirement applicationRequirement : applicationRequirements) {
            ApplicationRequirementFactoryVO applicationRequirementFactoryVO = applicationRequirementFactory.getApplicationRequirementFactoryService(applicationRequirement.getType().getCode())
                    .applicationRequirement(user, applicationRequirement, type);
            list.add(applicationRequirementFactoryVO);
        }
        // 这个set里面会把数据匹配到对应的字段上,操作都在set中
        newPerformanceVO.setResultList(list);
        Integer teamCityServiceCenter = userWorkRoomDao.getsHowManyCommunityOutletsAreIncludedInTheSpecifiedCollection(userId);
        newPerformanceVO.setTeamCommunityNetwork(teamCityServiceCenter);
        Integer teamCommunityNetwork = userCityServerCentreDao.teamCityServiceCenter(userId);
        newPerformanceVO.setTeamCityServiceCenter(teamCommunityNetwork);
        return newPerformanceVO;
    }
    @Override
    public void deleteByUserIdAndType(Long userId,Integer type) {
        serviceCenterAuditDao.deleteByUserId(userId,type);
    }
}
